import os
import time
from enum import StrEnum
from pathlib import Path

import aiofiles
from fastapi import UploadFile
from miniopy_async import Minio
from miniopy_async.helpers import ObjectWriteResult

from base.base_storage import BaseStorage


class FileStorageType(StrEnum):
    LOCAL = "local"
    TENCENT = "tencent"
    MINIO = "minio"


class LocalStorage(BaseStorage):
    UPLOAD_DIR = "static/fileserver"

    async def generate_file_info(self, file: UploadFile) -> dict:
        # 确保上传目录存在
        Path(self.UPLOAD_DIR).mkdir(parents=True, exist_ok=True)

        # 生成基于时间戳的文件名
        timestamp = int(time.time() * 1000)
        file_extension = Path(file.filename).suffix
        new_filename = f"{timestamp}{file_extension}"

        # 构建文件路径
        file_path = Path(self.UPLOAD_DIR) / new_filename

        # 读取并异步保存文件
        data = await file.read()
        async with aiofiles.open(file_path, "wb") as f:  # 移除 encoding 参数
            await f.write(data)

        # 生成文件URL
        file_url = f"{self.UPLOAD_DIR}/{new_filename}"

        # 如果是图片，生成图片哈希
        file_hash = None
        if file.content_type.startswith("image"):
            file_hash = await self._generate_image_hash(data)

        return {
            "file_url": file_url,
            "filename": file.filename,
            "filesize": len(data),
            "file_hash": file_hash,
        }


class TencentStorage(BaseStorage):

    async def generate_file_info(self, file: UploadFile) -> dict:
        pass


class MinioStorage(BaseStorage):

    async def generate_file_info(self, file: UploadFile) -> dict:
        client = Minio(
            endpoint=os.getenv("MINIO_ENDPOINT"),
            access_key=os.getenv("MINIO_ACCESS_KEY"),
            secret_key=os.getenv("MINIO_SECRET_KEY"),
            secure=bool(os.getenv("MINIO_SECURE")),
        )
        # 读取文件内容以获取文件大小
        data = await file.read()
        file_size = len(data)

        # 重置文件指针到开始位置
        await file.seek(0)

        bucket_name = os.getenv("MINIO_BUCKET")

        # 其余代码保持不变...
        resp: ObjectWriteResult = await client.put_object(
            bucket_name=bucket_name,
            object_name=file.filename,
            data=file,
            length=file_size,
            content_type=file.content_type,
        )
        obj_name = resp.object_name

        return {
            "file_url": f"{'https' if bool(os.getenv('MINIO_SECURE')) else 'http'}://{os.getenv('MINIO_ENDPOINT')}/{bucket_name}/{obj_name}",
            "filename": file.filename,
            "filesize": file_size,
            "file_hash": await self._generate_image_hash(data),
        }


class StorageFactory:
    @staticmethod
    def get_storage(storage_type: FileStorageType) -> BaseStorage:
        if storage_type == FileStorageType.LOCAL:
            return LocalStorage()
        if storage_type == FileStorageType.TENCENT:
            return TencentStorage()
        if storage_type == FileStorageType.MINIO:
            return MinioStorage()
